package com.yahoo.platform.yui.compressor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;

import com.yahoo.platform.util.DirHelper;

public class JavaScriptHtmlCompositor {

	private static Logger logger = Logger.getLogger(JavaScriptHtmlCompositor.class);
	// private String srcFolder = null;
	// private String dstFolder = null;
	// private ArrayList<String> jsList = null;
	// private ArrayList<String> htmlList = null;
	private List<File> jsFiles = null;
	private List<File> htmlFiles = null;
	private String tplPrefix = "tpl_";
	private String charset = "UTF-8";
	private int linebreakops = 8000;
	private String srcRootFolder = null;
	private String dstRootFolder = null;

	public JavaScriptHtmlCompositor() {
		//jsFiles = new ArrayList<File>();
		jsFiles = new CopyOnWriteArrayList<File>();
		htmlFiles = new CopyOnWriteArrayList<File>();
	}

	public JavaScriptHtmlCompositor(String srcRootFolder, String dstRootFolder) {
		this.srcRootFolder = srcRootFolder;
		this.dstRootFolder = dstRootFolder;
		jsFiles = new CopyOnWriteArrayList<File>();
		htmlFiles = new CopyOnWriteArrayList<File>();
	}

	public JavaScriptHtmlCompositor(String charset, int linebreakops) {
		this.charset = charset;
		this.linebreakops = linebreakops;
		jsFiles = new CopyOnWriteArrayList<File>();
		htmlFiles = new CopyOnWriteArrayList<File>();
	}

	public JavaScriptHtmlCompositor(String srcFolder, String dstFolder,
			String charset) {
		this.charset = charset;
		jsFiles = new CopyOnWriteArrayList<File>();
		htmlFiles = new CopyOnWriteArrayList<File>();
	}

	private void listFiles(String srcFolder) {
		File folder = new File(srcFolder);
		File[] files = folder.listFiles();
		for (File f : files) {
			String fileName = f.getName();
			if (fileName.toLowerCase().endsWith(".js"))
				jsFiles.add(f);
			else if (fileName.toLowerCase().endsWith(".html"))
				htmlFiles.add(f);
		}
	}

	public boolean composite() {
		return true;
	}

	public void composite(String jsFile) {
		String jsRelativePath = jsFile.replace(srcRootFolder, "");
		String jsFileName = jsFile.substring(jsFile.lastIndexOf("\\") + 1);
		String jsFileNamePrefix = jsFileName.substring(0, jsFileName.length()
				- ".js".length());
		JavaScriptCompressor javaScriptCompressor = null;
		try {
			javaScriptCompressor = new JavaScriptCompressor(jsFile,
					new ErrorReporter() {

						public void warning(String message, String sourceName,
								int line, String lineSource, int lineOffset) {
							if (line < 0) {
								System.err.println("\n[WARNING] " + message);
							} else {
								System.err.println("\n[WARNING] " + line + ':'
										+ lineOffset + ':' + message);
							}
						}

						public void error(String message, String sourceName,
								int line, String lineSource, int lineOffset) {
							if (line < 0) {
								System.err.println("\n[ERROR] " + message);
							} else {
								System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message);
								//String errMessage = "\n[ERROR] " + String.valueOf(line) + ":" + String.valueOf(lineOffset) + ":" + message;
								//logger.error(errMessage);
							}
						}

						public EvaluatorException runtimeError(String message,
								String sourceName, int line, String lineSource,
								int lineOffset) {
							error(message, sourceName, line, lineSource,
									lineOffset);
							return new EvaluatorException(message);
						}
					});
		} catch (EvaluatorException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(javaScriptCompressor == null)
			return;
		String jsString = javaScriptCompressor.compress(linebreakops, false, false, false, true);
		String htmlTplPrefix = tplPrefix + jsFileNamePrefix;
		String htmlString = "";
		HtmlCompressor htmlCompressor = new HtmlCompressor();
		String srcFolder = jsFile.substring(0, jsFile.lastIndexOf("\\"));
		List<File> htmlFiles2 = DirHelper.listFiles(srcFolder, ".html");
		for (File htmlFile : htmlFiles2) {
			String htmlFileName = htmlFile.getName();
			if (htmlFileName.startsWith(htmlTplPrefix)) {
				String htmlFileNamePrefix = htmlFileName.substring(0,
						htmlFileName.length() - ".html".length());
				htmlString += "var ";
				htmlString += htmlFileNamePrefix;
				htmlString += "='";
				try {
					htmlString += htmlCompressor.compress(htmlFile
							.getAbsolutePath());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				htmlString += "';\n";
			}
		}
		htmlString += jsString;
		// DirHelper.checkDir(dstFolder);

		Writer out = null;
		String outputFilename = dstRootFolder + jsRelativePath;
		try {
			out = new OutputStreamWriter(new FileOutputStream(outputFilename),
					charset);
		} catch (UnsupportedEncodingException | FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			out.write(htmlString);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (out != null)
				try {
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}

	public boolean composite(String srcFolder, String dstRootFolder) {
		boolean success = false;

		listFiles(srcFolder);

		for (File jsFile : jsFiles) {
			String jsFileName = jsFile.getName();
			String jsFileNamePrefix = jsFileName.substring(0,
					jsFileName.length() - ".js".length());
			JavaScriptCompressor javaScriptCompressor = null;
			try {
				javaScriptCompressor = new JavaScriptCompressor(
						jsFile.getAbsolutePath(), new ErrorReporter() {

							public void warning(String message,
									String sourceName, int line,
									String lineSource, int lineOffset) {
								if (line < 0) {
									System.err.println("\n[WARNING] " + message + " in " + sourceName);
									//logger.error("\n[WARNING] " + message);
								} else {
									System.err.println("\n[WARNING] " + line
											+ ':' + lineOffset + ':' + message + " in " + sourceName);
									//logger.error("\n[WARNING] " + line
									//		+ ':' + lineOffset + ':' + message);
								}
							}

							public void error(String message,
									String sourceName, int line,
									String lineSource, int lineOffset) {
								if (line < 0) {
									System.err.println("\n[ERROR] " + message + " in " + sourceName);
									//logger.error("\n[ERROR] " + message);
								} else {
									System.err.println("\n[ERROR] " + line
											+ ':' + lineOffset + ':' + message + " in " + sourceName);
									//logger.error("\n[ERROR] " + line
									//		+ ':' + lineOffset + ':' + message);
								}
							}

							public EvaluatorException runtimeError(
									String message, String sourceName,
									int line, String lineSource, int lineOffset) {
								error(message, sourceName, line, lineSource,
										lineOffset);
								//return new EvaluatorException(message);
								return new EvaluatorException(message, sourceName, line);
							}
						});
			} catch (EvaluatorException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("同步文件：" + e.sourceName() + "失败");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("同步文件：" + jsFileName + "失败");
			}

			if (javaScriptCompressor != null) {
				String jsString = javaScriptCompressor.compress(linebreakops,
						false, false, false, true);
				String htmlTplPrefix = tplPrefix + jsFileNamePrefix;
				String htmlString = "";
				HtmlCompressor htmlCompressor = new HtmlCompressor();
				for (File htmlFile : htmlFiles) {
					String htmlFileName = htmlFile.getName();
					if (htmlFileName.startsWith(htmlTplPrefix)) {
						String htmlFileNamePrefix = htmlFileName.substring(0,
								htmlFileName.length() - ".html".length());
						htmlString += "var ";
						htmlString += htmlFileNamePrefix;
						htmlString += "='";
						try {
							htmlString += htmlCompressor.compress(htmlFile
									.getAbsolutePath());
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						htmlString += "';\n";
					}
				}
				htmlString += jsString;
				// DirHelper.checkDir(dstFolder);

				Writer out = null;
				String outputFilename = dstRootFolder + "\\" + jsFileName;
				try {
					out = new OutputStreamWriter(new FileOutputStream(
							outputFilename), charset);
				} catch (UnsupportedEncodingException | FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					out.write(htmlString);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} finally {
					if (out != null)
						try {
							out.close();
							success = true;
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				}
			}

			htmlFiles.removeAll(htmlFiles);
			jsFiles.removeAll(jsFiles);
		}
		return success;
	}

	public class FileFilter implements FilenameFilter {
		private Pattern pattern;

		public FileFilter(String regex) {
			pattern = Pattern.compile(regex);
		}

		public boolean accept(File dir, String name) {
			return pattern.matcher(name).matches();
		}
	}
}
